// import decodeGif from 'decode-gif'
import { parseGIF, decompressFrames } from 'gifuct-js'
function colorAdd(color: ArrayLike<number>, color2: ArrayLike<number>) {
  if (color2[3] == 0) {
    return color
  }
  const oa = color[3] / 255
  const ca = color2[3] / 255
  const or = color[0] * oa * (1 - ca)
  const og = color[1] * oa * (1 - ca)
  const ob = color[2] * oa * (1 - ca)
  const cr = color2[0] * ca
  const cg = color2[1] * ca
  const cb = color2[2] * ca
  const rgba = [
    or + cr,
    og + cg,
    ob + cb,
    color2[3] == 0 ? color[3] : color2[3],
    // color2[3],
  ]
  const v = rgba.map((v) => Math.min(255, Math.max(0, Math.round(v))))
  return v
}
const fileToBuffer = async (file: File) => {
  return new Promise<ArrayBuffer>((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = (e) => {
      resolve
        ? resolve(e.target.result as ArrayBuffer)
        : reject(new Error('Failed to read file'))
    }
    reader.onerror = reject
    reader.readAsArrayBuffer(file)
  })
}
function setImageData(
  imageData: ImageData,
  data: number[],
  colorTable: [number, number, number][],
  transparentIndex?: number
) {
  for (let i = 0; i < data.length; i += 1) {
    if (transparentIndex == data[i]) {
      continue
    }
    imageData.data.set([...colorTable[data[i]], 255], i * 4)
  }
}
export interface GifResult {
  frames: File[]
  width: number
  height: number
  duration: number
}
export async function processGIF(file: File): Promise<GifResult> {
  const buffer = await fileToBuffer(file)
  const gif = parseGIF(buffer)
  const framesList = decompressFrames(gif, true)

  const frames: File[] = []

  // 为每帧创建独立的canvas，避免状态污染
  let currentCanvas = document.createElement('canvas')
  currentCanvas.width = gif.lsd.width
  currentCanvas.height = gif.lsd.height
  let ctx = currentCanvas.getContext('2d')!

  // 保存前一帧状态，用于disposalType=3的情况
  let previousCanvas: HTMLCanvasElement | null = null

  for (let index = 0; index < framesList.length; index++) {
    const frame = framesList[index]
    const { left, top, width, height } = frame.dims

    // 保存当前状态（用于disposalType=3）
    if (frame.disposalType === 3 && previousCanvas === null) {
      previousCanvas = document.createElement('canvas')
      previousCanvas.width = currentCanvas.width
      previousCanvas.height = currentCanvas.height
      const prevCtx = previousCanvas.getContext('2d')!
      prevCtx.drawImage(currentCanvas, 0, 0)
    }

    // 处理当前帧
    const imageData = ctx.getImageData(left, top, width, height)
    setImageData(
      imageData,
      frame.pixels,
      frame.colorTable,
      frame.transparentIndex
    )
    ctx.putImageData(imageData, left, top)

    // 导出当前帧
    const blob = await toBlob(currentCanvas, 'image/png')
    frames.push(new File([blob], `${index}.png`, { type: 'image/png' }))

    // 根据disposalType处理画布状态
    switch (frame.disposalType) {
      case 0: // 未指定，通常当作1处理
      case 1: // 保留，不做清理
        break

      case 2: // 恢复到背景色
        ctx.clearRect(left, top, width, height)
        break

      case 3: // 恢复到前一帧状态
        if (previousCanvas) {
          ctx.drawImage(previousCanvas, 0, 0)
          previousCanvas = null
        }
        break
    }

    // 为下一帧的disposalType=3准备
    if (
      index < framesList.length - 1 &&
      framesList[index + 1].disposalType === 3
    ) {
      previousCanvas = document.createElement('canvas')
      previousCanvas.width = currentCanvas.width
      previousCanvas.height = currentCanvas.height
      const prevCtx = previousCanvas.getContext('2d')!
      prevCtx.drawImage(currentCanvas, 0, 0)
    }
  }

  return {
    frames,
    width: currentCanvas.width,
    height: currentCanvas.height,
    duration: framesList.reduce((sum, frame) => sum + (frame.delay || 0), 0),
  }
}

const toBlob = (canvas: HTMLCanvasElement, type: string, quality?: number) => {
  return new Promise<Blob>((resolve, reject) => {
    canvas.toBlob(
      (blob) => {
        if (blob) {
          resolve(blob)
        } else {
          reject(new Error('Failed to create blob'))
        }
      },
      type,
      quality
    )
  })
}
